using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Reflection;
using System.Xml;
using System.Web;

namespace CodePlex.OpenSearch
{

    /// <summary>
    /// Common utility functions.
    /// </summary>
    public static class Util
    {


        /// <summary>
        /// Loads a resource given an assembly-relative resource name and an anchor type.
        /// </summary>
        public static Stream GetResourceAsStream<T>(string name)
        {
            Assembly a = typeof(T).Assembly;

            return a.GetManifestResourceStream(a.GetName().Name + "." + name);
        }

        /// <summary>
        /// Allows the rendering of starting/ending xml elements to leverage the c# using statement.
        /// </summary>
        /// <example>
        /// <code>
        /// using (Util.StartElement(writer, "body"))
        /// {
        ///     writer.WriteElementString("h4", "Content Page");
        ///     writer.WriteElementString("p", "This page includes the necessary opensearch auto-discovery information.");
        /// }
        /// </code>
        /// </example>
        public static IDisposable StartElement(XmlTextWriter writer, string name)
        {

            writer.WriteStartElement(name);

            return new ElementScope(writer);
        }


        /// <summary>
        /// Gets the path of the current request relative to the application base path.
        /// </summary>
        public static string RelativePath(HttpContext context)
        {
            if (context.Request.ApplicationPath == "/")
            {
                return context.Request.Path;
            }
            else
            {
                return context.Request.Path.Substring(context.Request.ApplicationPath.Length);
            }
        }


        /// <summary>
        /// Redirects to a path relative to the application base path.
        /// </summary>
        public static void RelativeRedirect(HttpContext context, string relativePath)
        {
            string redir = context.Request.ApplicationPath + relativePath;
            if (context.Request.ApplicationPath == "/")
            {
                redir = relativePath;
            }

            context.Response.Redirect(redir);
        }





















        internal static string AtomDate(DateTime value)
        {
            return value.ToUniversalTime().ToString("s") + "Z";
        }
        
        internal static void BufferedTransfer(Stream input, Stream output)
        {

            int bufferSize = 4096;

            BufferedStream bufferedInputStream = new BufferedStream(input, bufferSize);


            byte[] bytes = new byte[bufferSize];

            long totalBytes = 0;
            int read = 0;
            while ((read = bufferedInputStream.Read(bytes, 0, bytes.Length)) != 0)
            {
                output.Write(bytes, 0, read);

                totalBytes += read;
            }

            output.Flush();

        }



        internal static string UrlEncode(string value)
        {
            return System.Web.HttpUtility.UrlEncode(value);
        }


        internal static string UrlDecode(string value)
        {
            return System.Web.HttpUtility.UrlDecode(value);
        }





        internal static string JsonQuote(string value)
        {
            return "\"" + value
                .Replace("\\","\\\\")
                .Replace("\"", "\\\"") 
                + "\"";
        }

        internal static string JsonArray(params string[] values)
        {
            return string.Format("[{0}]", string.Join(",", values));
        }

        internal static string JsonArray(IEnumerable<string> values)
        {

            return string.Format("[{0}]", string.Join(",", new List<string>(values).ToArray()));
        }




      






        private class ElementScope : IDisposable
        {
            private readonly XmlTextWriter _writer;
            internal ElementScope(XmlTextWriter writer)
            {
                _writer = writer;
            }

            public void Dispose()
            {
                _writer.WriteEndElement();
            }

          
        }
}
}
